package com.meilai.project.service.business.media.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.meilai.project.constant.BuildingCorrespondingPointEnum;
import com.meilai.project.dto.business.intentionScheme.*;
import com.meilai.project.dto.media.AbMediaPointDTO;
import com.meilai.project.dto.media.ImportAbPointDTO;
import com.meilai.project.dto.media.MediaPointDTO;
import com.meilai.project.entity.business.building.BuildingArea;
import com.meilai.project.entity.business.building.BuildingAreaTypeMediaTypeRelation;
import com.meilai.project.entity.business.installOrder.WorkerSubmitPhoto;
import com.meilai.project.entity.media.MediaPoint;
import com.meilai.project.entity.media.MediaPointAB;
import com.meilai.project.entity.media.MediaType;
import com.meilai.project.exception.CommonException;
import com.meilai.project.mapper.business.building.BuildingAreaMapper;
import com.meilai.project.mapper.business.building.BuildingAreaTypeMediaTypeRelationMapper;
import com.meilai.project.mapper.business.media.MediaPointABMapper;
import com.meilai.project.mapper.business.media.MediaPointMapper;
import com.meilai.project.service.business.building.BuildingAreaService;
import com.meilai.project.service.business.installOrder.WorkerSubmitPhotoService;
import com.meilai.project.service.business.intentionScheme.IntentionSchemeService;
import com.meilai.project.service.business.media.MediaPointABService;
import com.meilai.project.service.business.media.MediaPointService;
import com.meilai.project.service.business.media.MediaTypeService;
import com.meilai.project.service.media.MediaPointOccupySnapshotService;
import com.meilai.project.service.middleware.AttachmentService;
import com.meilai.project.util.FileUtil;
import com.meilai.project.vo.business.media.MediaPointVO;
import com.meilai.project.vo.business.media.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.groupingBy;

/**
 * @author 张驰
 * @date 2022/1/9 23:02
 */
@Slf4j
@Service
public class MediaPointServiceImpl extends ServiceImpl<MediaPointMapper, MediaPoint> implements MediaPointService {
    private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
    @Autowired
    private MediaPointABService mediaPointABService;
    @Autowired
    private MediaPointABMapper mediaPointABMapper;
    @Autowired
    private IntentionSchemeService intentionSchemeService;
    @Autowired
    private MediaTypeService mediaTypeService;
    @Autowired
    private WorkerSubmitPhotoService workerSubmitPhotoService;
    @Autowired
    private MediaPointOccupySnapshotService mediaPointOccupySnapshotService;
    @Autowired
    private BuildingAreaService buildingAreaService;

    @Autowired
    private BuildingAreaTypeMediaTypeRelationMapper buildingAreaTypeMediaTypeRelationMapper;

    @Autowired
    private AttachmentService attachmentService;

    @Autowired
    private BuildingAreaMapper buildingAreaMapper;

    @Value("${static-resource.file-space}")
    private String tmpPath;

    /**
     * 填充Excel
     *
     * @param data              数据
     * @param typeId            楼盘类型
     * @param point_type_id_arr 对应的点位类型ID
     * @param index             当前行
     */
    public static void fillExcel(BuildingPointVO data, Long typeId, List<Long> point_type_id_arr, int index, HSSFSheet sheet, HSSFCellStyle warpTextCellStyle, HSSFCellStyle textCenterCellStyle, Boolean floor_group, Integer abType) {
        HSSFRow row = sheet.createRow(index);
        HSSFCell cell = row.createCell(0);
        // 填充序号
        cell.setCellValue(index - 2);
        cell.setCellStyle(textCenterCellStyle);
        // 填充所在区
        HSSFCell cell1 = row.createCell(1);
        cell1.setCellValue(data.getArea());
        cell1.setCellStyle(textCenterCellStyle);
        // 填充楼盘名称
        HSSFCell cell2 = row.createCell(2);
        cell2.setCellValue(data.getName());
        cell2.setCellStyle(textCenterCellStyle);
        // 填充详细地址
        HSSFCell cell3 = row.createCell(3);
        cell3.setCellValue(data.getAddress());
        cell3.setCellStyle(textCenterCellStyle);
        // 填充可选单元格
        for (int i = 0; i < point_type_id_arr.size(); i++) {
            StringBuilder s = new StringBuilder();
            // 如果是住宅类型
            if (typeId.equals(78L)) {
                Long id = point_type_id_arr.get(i);
                List<MediaPointSimpleVO> mediaPointList = data.getPointTypeCountVOMap().get(id).getMediaPointList();
                if (floor_group) {
                    Map<String, List<MediaPointSimpleVO>> floorMap = mediaPointList.stream().collect(groupingBy(MediaPointSimpleVO::getFloor));
                    List<String> keyList = new ArrayList<>(floorMap.keySet());
                    for (int j = 0; j < keyList.size(); j++) {
                        String key = keyList.get(j);
                        if (j == keyList.size() - 1) {
                            s.append(key).append("层：").append(floorMap.get(key).size()).append("个");
                        } else {
                            s.append(key).append("层：").append(floorMap.get(key).size()).append("个\r\n");
                        }
                    }
                } else {
                    s.append(mediaPointList.size()).append("个");
                }
            } else if (typeId.equals(82L)) { // 如果是综合市场类型
                Long id = point_type_id_arr.get(i);
                List<MediaPointSimpleVO> mediaPointList = data.getPointTypeCountVOMap().get(id).getMediaPointList();
                if (abType == 1) {
                    mediaPointList = mediaPointList.stream().filter(point -> point.getAb_type_id().equals(57L)).collect(Collectors.toList());
                } else if (abType == 2) {
                    mediaPointList = mediaPointList.stream().filter(point -> point.getAb_type_id().equals(58L)).collect(Collectors.toList());
                }
                Map<Long, List<MediaPointSimpleVO>> surfaceMap = mediaPointList.stream().collect(groupingBy(MediaPointSimpleVO::getAb_type_id));
                List<Long> keyList = new ArrayList<>(surfaceMap.keySet());
                for (int j = 0; j < keyList.size(); j++) {
                    Long key = keyList.get(j);
                    if (j == keyList.size() - 1) {
                        s.append(key.equals(57L) ? "A面：" : "B面：").append(surfaceMap.get(key).size()).append("个");
                    } else {
                        s.append(key.equals(57L) ? "A面：" : "B面：").append(surfaceMap.get(key).size()).append("个\r\n");
                    }
                }
            } else { // 其他类型
                Long id = point_type_id_arr.get(i);
                PointTypeCountVO countVO = data.getPointTypeCountVOMap().get(id);
                Integer point_type_count = 0;
                if (countVO != null){
                    point_type_count = countVO.getPoint_type_count();
                }
                s.append(point_type_count).append("个");
            }
            // 填充统计数据
            HSSFCell countCell = row.createCell(4 + i);
            countCell.setCellStyle(warpTextCellStyle);
            countCell.setCellValue(s.toString());
        }
    }

    /**
     * 创建Excel
     *
     * @param list              楼盘数据集合
     * @param typeId            楼盘类型
     * @param point_type_id_arr 楼盘对应点位枚举类
     * @return HSSFWorkbook
     */
    public static HSSFWorkbook createExcel(List<BuildingPointVO> list, Long typeId, List<Long> point_type_id_arr, Map<Long, String> pointTypeMap, LocalDate startDate, LocalDate endDate, Boolean floor_group, Integer abType) {
        // 创建表格对象
        HSSFWorkbook wb = new HSSFWorkbook();
        // 创建换行样式
        HSSFCellStyle warpTextCellStyle = wb.createCellStyle();
        warpTextCellStyle.setWrapText(true);
        warpTextCellStyle.setAlignment(HorizontalAlignment.CENTER);
        warpTextCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        // 创建居中样式
        HSSFCellStyle textCenterCellStyle = wb.createCellStyle();
        textCenterCellStyle.setAlignment(HorizontalAlignment.CENTER);
        textCenterCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        // 创建sheet
        HSSFSheet sheet = wb.createSheet();
        // 创建表头
        HSSFRow firstRow = sheet.createRow(0);
        HSSFCell firstRowCell = firstRow.createCell(0);
        firstRowCell.setCellValue(startDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + "至" + endDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        firstRowCell.setCellStyle(textCenterCellStyle);
        HSSFRow row = sheet.createRow(1);
        HSSFRow row1 = sheet.createRow(2);
        HSSFCell cell = row.createCell(0);
        cell.setCellValue("序号");
        cell.setCellStyle(textCenterCellStyle);
        HSSFCell cell1 = row.createCell(1);
        cell1.setCellValue("所在区");
        cell1.setCellStyle(textCenterCellStyle);
        HSSFCell cell2 = row.createCell(2);
        cell2.setCellValue("楼盘名称");
        cell2.setCellStyle(textCenterCellStyle);
        HSSFCell cell3 = row.createCell(3);
        cell3.setCellValue("详细地址");
        cell3.setCellStyle(textCenterCellStyle);
        //设置宽度
        sheet.setColumnWidth(0, 256 * 10);
        sheet.setColumnWidth(1, 256 * 20);
        sheet.setColumnWidth(2, 256 * 30);
        sheet.setColumnWidth(3, 256 * 50);
        // 设置跨行
        sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 3 + point_type_id_arr.size()));
        sheet.addMergedRegion(new CellRangeAddress(1, 2, 0, 0));
        sheet.addMergedRegion(new CellRangeAddress(1, 2, 1, 1));
        sheet.addMergedRegion(new CellRangeAddress(1, 2, 2, 2));
        sheet.addMergedRegion(new CellRangeAddress(1, 2, 3, 3));
        for (int i = 0; i < point_type_id_arr.size(); i++) {
            sheet.setColumnWidth(4 + i, 256 * 15);
            HSSFCell point_name_cell = row.createCell(4 + i);
            point_name_cell.setCellValue(pointTypeMap.get(point_type_id_arr.get(i)));
            point_name_cell.setCellStyle(textCenterCellStyle);
            HSSFCell cell4 = row1.createCell(4 + i);
            cell4.setCellValue("可选");
            cell4.setCellStyle(textCenterCellStyle);
        }
        int index = 3;
        for (BuildingPointVO data : list) {
            // 填充表格
            fillExcel(data, typeId, point_type_id_arr, index, sheet, warpTextCellStyle, textCenterCellStyle, floor_group, abType);
            index++;
        }
        return wb;
    }

    /**
     * 创建Excel
     *
     * @param list 楼盘数据集合
     * @return HSSFWorkbook
     */
    public static HSSFWorkbook createExcelBySmartBox(List<BuildingPointVO> list, List<JSONObject> jsonList, List<Long> point_type_id_arr, Map<Long, String> pointTypeMap, LocalDate startDate, LocalDate endDate, Boolean floor_group) {
        // 创建表格对象
        HSSFWorkbook wb = new HSSFWorkbook();
        /**
         * 单元格样式
         */
        HSSFCellStyle tbodyCellStyle = setExcelTbodyCellStyle(wb);
        HSSFCellStyle theadCellStyle = setExcelTheadCellStyle(wb, tbodyCellStyle);
        HSSFCellStyle titleCellStyle = setExcelTitleCellStyle(wb, tbodyCellStyle);
        HSSFCellStyle timeCellStyle = setExcelTimeCellStyle(wb, tbodyCellStyle);

        // 基础列
        String[] theadArr = new String[]{"序号", "项目名称", "区域", "项目地址", "覆盖地区", "二级分类", "均价（元/平方）", "年份", "入住率", "居住规模约（人）", "受众描述", "最高楼层", "楼栋数", "单元数", "电梯数", "媒体点位总数", "单次固定售卖", "禁投行业", "空余数量"};
        int theadLength = theadArr.length, index = theadLength - 1;

        // 创建sheet
        HSSFSheet sheet = wb.createSheet();
        // 创建表头
        HSSFRow row = sheet.createRow(0);
        row.setHeight((short) (50 * 20));
        HSSFCell cell = row.createCell(0);
        cell.setCellValue("社区智能框架点位空余表");
        cell.setCellStyle(titleCellStyle);
        // 设置跨行
        CellRangeAddress cellAddresses = new CellRangeAddress(0, 0, 0, index + point_type_id_arr.size());
        sheet.addMergedRegion(cellAddresses);
        RegionUtil.setBorderBottom(BorderStyle.THIN, cellAddresses, sheet);
        RegionUtil.setBorderLeft(BorderStyle.THIN, cellAddresses, sheet);
        RegionUtil.setBorderRight(BorderStyle.THIN, cellAddresses, sheet);
        RegionUtil.setBorderTop(BorderStyle.THIN, cellAddresses, sheet);

        HSSFRow row1 = sheet.createRow(1);
        row1.setHeight((short) (30 * 20));
        HSSFCell cell1 = row1.createCell(0);
        cell1.setCellValue(startDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + "至" + endDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        cell1.setCellStyle(timeCellStyle);
        // 设置跨行
        CellRangeAddress cellAddresses1 = new CellRangeAddress(1, 1, 0, index + point_type_id_arr.size());
        sheet.addMergedRegion(cellAddresses1);
        RegionUtil.setBorderBottom(BorderStyle.THIN, cellAddresses1, sheet);
        RegionUtil.setBorderLeft(BorderStyle.THIN, cellAddresses1, sheet);
        RegionUtil.setBorderRight(BorderStyle.THIN, cellAddresses1, sheet);
        RegionUtil.setBorderTop(BorderStyle.THIN, cellAddresses1, sheet);

        HSSFRow row2 = sheet.createRow(2);
        row2.setHeight((short) (20 * 20));
        HSSFRow row3 = sheet.createRow(3);
        row3.setHeight((short) (20 * 20));
        // 设置表头
        setExcelThead(sheet, row2, theadCellStyle, theadArr);
        for (int i = 0; i < point_type_id_arr.size(); i++) {
            sheet.setColumnWidth(theadLength + i, 256 * 15);
            HSSFCell point_name_cell = row2.createCell(theadLength + i);
            point_name_cell.setCellValue(pointTypeMap.get(point_type_id_arr.get(i)));
            point_name_cell.setCellStyle(theadCellStyle);
            HSSFCell cell3 = row3.createCell(theadLength + i);
            cell3.setCellValue("可选");
            cell3.setCellStyle(theadCellStyle);
        }
        // 设置表格内容
        fillExcelTbody(sheet, tbodyCellStyle, 4, theadLength, list, jsonList, point_type_id_arr, floor_group);

        return wb;
    }

    /**
     * 填充Excel
     *
     * @param list              数据
     * @param point_type_id_arr 对应的点位类型ID
     * @rowIndex 当前行
     */
    public static void fillExcelTbody(HSSFSheet sheet, HSSFCellStyle cellStyle, int rowIndex, int colLength, List<BuildingPointVO> list, List<JSONObject> jsonList, List<Long> point_type_id_arr, Boolean floor_group) {
        int idx = 1;
        Map<Long, Map<Long, PointTypeCountVO>> map = list.stream().collect(Collectors.toMap(BuildingPointVO::getId, BuildingPointVO::getPointTypeCountVOMap));
        for (JSONObject obj : jsonList) {
            HSSFRow row = sheet.createRow(rowIndex);
            int freeCount = 0;
            // 填充可选单元格
            for (int i = 0; i < point_type_id_arr.size(); i++) {
                StringBuilder s = new StringBuilder();
                // 如果是住宅类型
                Long id = point_type_id_arr.get(i);
                List<MediaPointSimpleVO> mediaPointList = map.get(obj.getLong("id")).get(id).getMediaPointList();
                if (floor_group) {
                    Map<String, List<MediaPointSimpleVO>> floorMap = mediaPointList.stream().collect(groupingBy(MediaPointSimpleVO::getFloor));
                    List<String> keyList = new ArrayList<>(floorMap.keySet());
                    for (int j = 0; j < keyList.size(); j++) {
                        String key = keyList.get(j);
                        if (j == keyList.size() - 1) {
                            s.append(key).append("层：").append(floorMap.get(key).size()).append("个");
                        } else {
                            s.append(key).append("层：").append(floorMap.get(key).size()).append("个\r\n");
                        }
                        freeCount += floorMap.get(key).size();
                    }
                } else {
                    s.append(mediaPointList.size()).append("个");
                    freeCount += mediaPointList.size();
                }
                // 填充统计数据
                HSSFCell cell = row.createCell(colLength + i);
                cell.setCellValue(s.toString());
                cell.setCellStyle(cellStyle);
            }

            for (int i = 0; i < colLength; i++) {
                HSSFCell cell = row.createCell(i);
                String key = String.valueOf(i);
                if (i == 0) cell.setCellValue(idx);
                else if (i == colLength - 1) cell.setCellValue(freeCount);
                else if (i == 6 || i == 9 || i == 12 || i == 13 || i == 14 || i == 15)
                    cell.setCellValue(obj.getDouble(key) == null ? 0 : obj.getDouble(key));
                else cell.setCellValue(obj.getString(key));
                cell.setCellStyle(cellStyle);
            }
            idx++;
            rowIndex++;
        }
    }

    /**
     * 表格内容样式
     *
     * @param wb
     * @return
     */
    private static HSSFCellStyle setExcelTbodyCellStyle(HSSFWorkbook wb) {
        HSSFCellStyle cellStyle = wb.createCellStyle();
        // 设置边框
        cellStyle.setBorderBottom(BorderStyle.THIN); // 下边框
        cellStyle.setBorderLeft(BorderStyle.THIN); // 左边框
        cellStyle.setBorderTop(BorderStyle.THIN); // 上边框
        cellStyle.setBorderRight(BorderStyle.THIN); // 右边框
        // 设置居中
        cellStyle.setAlignment(HorizontalAlignment.CENTER); // 居中
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        // 设置字体
        HSSFFont font = wb.createFont();
        font.setFontName("宋体");
        font.setFontHeightInPoints((short) 10); // 设置字体大小
        cellStyle.setFont(font); // 选择需要用到的字体格式
        // 设置自动换行:
        cellStyle.setWrapText(true); // 设置自动换行
        return cellStyle;
    }

    /**
     * 表头样式
     *
     * @param wb
     * @param style
     * @return
     */
    private static HSSFCellStyle setExcelTheadCellStyle(HSSFWorkbook wb, HSSFCellStyle style) {
        HSSFCellStyle cellStyle = wb.createCellStyle();
        cellStyle.cloneStyleFrom(style);
        HSSFFont font = wb.createFont();
        font.setFontName("宋体");
        font.setBold(true); // 字体加粗
        font.setFontHeightInPoints((short) 10); // 设置字体大小
        cellStyle.setFont(font); // 选择需要用到的字体格式
        return cellStyle;
    }

    /**
     * 标题样式
     *
     * @param wb
     * @param style
     * @return
     */
    private static HSSFCellStyle setExcelTitleCellStyle(HSSFWorkbook wb, HSSFCellStyle style) {
        HSSFCellStyle cellStyle = wb.createCellStyle();
        cellStyle.cloneStyleFrom(style);
        HSSFFont font = wb.createFont();
        font.setFontName("宋体");
        font.setBold(true); // 字体加粗
        font.setFontHeightInPoints((short) 20); // 设置字体大小
        cellStyle.setFont(font); // 选择需要用到的字体格式
        return cellStyle;
    }

    /**
     * 时间样式
     *
     * @param wb
     * @param style
     * @return
     */
    private static HSSFCellStyle setExcelTimeCellStyle(HSSFWorkbook wb, HSSFCellStyle style) {
        HSSFCellStyle cellStyle = wb.createCellStyle();
        cellStyle.cloneStyleFrom(style);
//        cellStyle.setAlignment(HorizontalAlignment.RIGHT);
//        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        return cellStyle;
    }

    private static void setExcelThead(HSSFSheet sheet, HSSFRow row, HSSFCellStyle cellStyle, String[] arr) {
        int len = arr.length;
        for (int i = 0; i < len; i++) {
            int width = 10;
            if (i == 1) width = 15;
            if (i == 3) width = 20;
            if (i == 4) width = 25;
            if (i == 10 || i == 16) width = 45;
            sheet.setColumnWidth(i, width * 256);
            HSSFCell cell = row.createCell(i);
            cell.setCellValue(arr[i]);
            cell.setCellStyle(cellStyle);
            CellRangeAddress cellAddresses = new CellRangeAddress(2, 3, i, i);
            sheet.addMergedRegion(cellAddresses);
            RegionUtil.setBorderBottom(BorderStyle.THIN, cellAddresses, sheet);
            RegionUtil.setBorderLeft(BorderStyle.THIN, cellAddresses, sheet);
            RegionUtil.setBorderRight(BorderStyle.THIN, cellAddresses, sheet);
            RegionUtil.setBorderTop(BorderStyle.THIN, cellAddresses, sheet);
        }
    }

    /**
     * 创建sheet
     *
     * @param wb
     * @param list
     * @param typeId
     * @param point_type_id_arr
     * @param pointTypeMap
     * @param startDate
     * @param endDate
     * @param floor_group
     * @param abType
     */
    public static void createSheet(HSSFWorkbook wb, String sheetName, List<BuildingPointVO> list, Long typeId, List<Long> point_type_id_arr, Map<Long, String> pointTypeMap, LocalDate startDate, LocalDate endDate, Boolean floor_group, Integer abType) {
        // 创建换行样式
        HSSFCellStyle warpTextCellStyle = wb.createCellStyle();
        warpTextCellStyle.setWrapText(true);
        warpTextCellStyle.setAlignment(HorizontalAlignment.CENTER);
        warpTextCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        // 创建居中样式
        HSSFCellStyle textCenterCellStyle = wb.createCellStyle();
        textCenterCellStyle.setAlignment(HorizontalAlignment.CENTER);
        textCenterCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        // 创建sheet
        HSSFSheet sheet = wb.createSheet(sheetName);
        // 创建表头
        HSSFRow firstRow = sheet.createRow(0);
        HSSFCell firstRowCell = firstRow.createCell(0);
        firstRowCell.setCellValue(startDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + "至" + endDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        firstRowCell.setCellStyle(textCenterCellStyle);
        HSSFRow row = sheet.createRow(1);
        HSSFRow row1 = sheet.createRow(2);
        HSSFCell cell = row.createCell(0);
        cell.setCellValue("序号");
        cell.setCellStyle(textCenterCellStyle);
        HSSFCell cell1 = row.createCell(1);
        cell1.setCellValue("所在区");
        cell1.setCellStyle(textCenterCellStyle);
        HSSFCell cell2 = row.createCell(2);
        cell2.setCellValue("楼盘名称");
        cell2.setCellStyle(textCenterCellStyle);
        HSSFCell cell3 = row.createCell(3);
        cell3.setCellValue("详细地址");
        cell3.setCellStyle(textCenterCellStyle);
        //设置宽度
        sheet.setColumnWidth(0, 256 * 10);
        sheet.setColumnWidth(1, 256 * 20);
        sheet.setColumnWidth(2, 256 * 30);
        sheet.setColumnWidth(3, 256 * 50);
        // 设置跨行
        sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 3 + point_type_id_arr.size()));
        sheet.addMergedRegion(new CellRangeAddress(1, 2, 0, 0));
        sheet.addMergedRegion(new CellRangeAddress(1, 2, 1, 1));
        sheet.addMergedRegion(new CellRangeAddress(1, 2, 2, 2));
        sheet.addMergedRegion(new CellRangeAddress(1, 2, 3, 3));
        for (int i = 0; i < point_type_id_arr.size(); i++) {
            sheet.setColumnWidth(4 + i, 256 * 15);
            HSSFCell point_name_cell = row.createCell(4 + i);
            point_name_cell.setCellValue(pointTypeMap.get(point_type_id_arr.get(i)));
            point_name_cell.setCellStyle(textCenterCellStyle);
            HSSFCell cell4 = row1.createCell(4 + i);
            cell4.setCellValue("可选");
            cell4.setCellStyle(textCenterCellStyle);
        }
        int index = 3;
        for (BuildingPointVO data : list) {
            // 填充表格
            fillExcel(data, typeId, point_type_id_arr, index, sheet, warpTextCellStyle, textCenterCellStyle, floor_group, abType);
            index++;
        }
    }


    @Override
    public List<String> getCodeByRegexp(String reg) {
        return baseMapper.getCodeByRegexp(reg);
    }

    @Override
    public JSONObject getABPointList(Long id) {
        JSONObject jsonObject = new JSONObject();
        if (id == null) {
            throw new CommonException("请先传入项目id");
        }
        List<MediaMarketVO> list = baseMapper.getMediaMarketList(id);
        List<MediaMarketVO> aList = new ArrayList<>();
        List<MediaMarketVO> bList = new ArrayList<>();
        if (list.size() > 0) {
            for (MediaMarketVO vo : list) {
                if (vo.getAb_type_id() == 57) {
                    aList.add(vo);
                } else if (vo.getAb_type_id() == 58) {
                    bList.add(vo);
                }
            }
        }
        jsonObject.put("aList", aList);
        jsonObject.put("bList", bList);
        return jsonObject;
    }

    @Override
    public boolean hasMediaPoint(Long media_type_spec) {
        LambdaQueryWrapper<MediaPoint> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(MediaPoint::getMedia_type_spec_id, media_type_spec);
        Integer count = baseMapper.selectCount(lambdaQueryWrapper);
        return count > 0;
    }

    @Override
    public List<Integer> listFloorSelections() {
        return baseMapper.listFloorSelections();
    }

    @Override
    public boolean saveList(List<MediaPointDTO> dto) {
        if (dto == null) {
            return true;
        }
        //校验批量录入的code是否有重复
        Map<String, MediaPointDTO> map = new HashMap<>();
        List<String> listRepeatCode = new ArrayList<>();
        //与数据库中存在的code比较是否重复
        List<MediaPoint> listMediaPoint = baseMapper.selectList(new QueryWrapper<MediaPoint>().isNull("deleted_at"));
        List<String> listHavedCode = new ArrayList<>();
        for (MediaPoint point : listMediaPoint) {
            listHavedCode.add(point.getCode());
        }
        for (MediaPointDTO point : dto) {
            String code = point.getCode();
            if (code == null && point.getBpoint() != null) {
                throw new CommonException("存在没填a面信息的数据，请核验！");
            } else if (code == null) {
                throw new CommonException("有编号为空！");
            }
            if (map.containsKey(code)) {
                listRepeatCode.add(code);
            } else {
                map.put(code, point);
            }
            if (listHavedCode.contains(code)) {
                listRepeatCode.add(code);
            }
        }
        if (CollectionUtils.isNotEmpty(listRepeatCode)) {
            throw new CommonException("编号应唯一，以下编号存在重复值：" + listRepeatCode.toString());
        }

        for (MediaPointDTO point : dto) {
            if (point == null) {
                break;
            }
            Long a_id = null;
            if (point.getCode() != null) {
                MediaPoint temp = new MediaPoint();
                temp.setMedia_type_spec_id(point.getMedia_type_specs_id());
                BeanUtils.copyProperties(point, temp);
                temp.setQrcode(getUUID());
                save(temp);
                MediaPoint point1 = getOne(new QueryWrapper<MediaPoint>().eq("code", temp.getCode()).isNull("deleted_at"));
                a_id = point1.getId();
            }
            Long b_id = null;
            if (point.getBpoint() != null && StringUtils.isNotEmpty(point.getBpoint().getCode())) {
                AbMediaPointDTO bMediaPointDTO = point.getBpoint();
                MediaPoint temp = new MediaPoint();
                temp.setMedia_type_spec_id(bMediaPointDTO.getMedia_type_specs_id());
                BeanUtils.copyProperties(bMediaPointDTO, temp);
                temp.setQrcode(getUUID());
                save(temp);
                MediaPoint point1 = getOne(new QueryWrapper<MediaPoint>().eq("code", temp.getCode()).isNull("deleted_at"));
                b_id = point1.getId();
            }
            if (a_id != null && b_id != null) {
                MediaPointAB mediaPointAB = new MediaPointAB();
                mediaPointAB.setA_point_id(a_id);
                mediaPointAB.setB_point_id(b_id);
                mediaPointABService.save(mediaPointAB);
            }
        }
        return true;
    }

    //获取uuid
    private String getUUID() {
        return UUID.randomUUID().toString().trim().replace("-", "");
    }

    @Override
    public CommonPointListVO selectList(MediaPointDTO searchDTO) {
        List<MediaPointVO> list = baseMapper.listMediaPoint(searchDTO);
        CommonPointListVO commonPointListVO = new CommonPointListVO();
        List<MediaPointVO> new_list = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(list)) {
            int allCount = list.size();
            int publishCount = 0;
            int lockCount = 0;

            // 已锁定的点位
            Set<Long> lockPointIds = new HashSet<>(mediaPointOccupySnapshotService.getLockPointIdsByIds(list.stream().map(MediaPointVO::getId).collect(Collectors.toList())));
            lockCount = lockPointIds.size();
            // 已上刊的点位
            Set<Long> publishMediaPointIds = new HashSet<>(baseMapper.getPublishMediaPointIds(list.stream().map(MediaPointVO::getId).collect(Collectors.toList())));
            publishCount = publishMediaPointIds.size();

            //设置预留字段
            commonPointListVO.setFreeCount(allCount - publishCount - lockCount);
            commonPointListVO.setLockCount(lockCount);
            commonPointListVO.setOptionalCount(publishCount);
            for (MediaPointVO vo : list) {
                //设置预留锁定字段
                vo.setLock_status(publishMediaPointIds.contains(vo.getId())?1:(lockPointIds.contains(vo.getId())?2:3));

                Long ab_type_id = vo.getAb_type_id();
                if (ab_type_id == null) {
                    new_list.add(vo);
                }
                if (ab_type_id != null && ab_type_id == 57L) {
                    Long a_point_id = vo.getId();
                    AbMediaPointDTO b_point = baseMapper.getBpointByAPointId(a_point_id);
                    if (b_point != null) {
                        vo.setBPoint(b_point);
                    }
                    new_list.add(vo);
                }
                if (ab_type_id != null && ab_type_id == 58L) {
                    Long b_point_id = vo.getId();
                    AbMediaPointDTO a_point = baseMapper.getApointByBPointId(b_point_id);
                    if (a_point != null && a_point.getId() != null) {
                        continue;
                    } else {
                        MediaPointVO mediaPointVO = new MediaPointVO();
                        AbMediaPointDTO b_point = new AbMediaPointDTO();
                        BeanUtils.copyProperties(vo, b_point);
                        mediaPointVO.setBPoint(b_point);
                        new_list.add(mediaPointVO);
                    }
                }

            }
            commonPointListVO.setMediaPointList(new_list);
        }
        return commonPointListVO;
    }

    @Override
    public MediaPointDTO getOneById(Long id) {
        return getOneById(id);
    }

    @Override
    public boolean delete(Long id) {
        LocalDateTime now = LocalDateTime.now();
        MediaPoint temp = getById(id);
        if (temp == null) return false;
        MediaPoint mediaPoint = new MediaPoint();
        mediaPoint.setId(id);
        mediaPoint.setDeleted_at(now);
        //return updateById(mediaPoint);
        return update(new UpdateWrapper<MediaPoint>().eq("id", id).set("deleted_at", now).set("status", 0));
    }

    @Override
    public boolean checkCode(String code, Long id) {
        List<MediaPoint> list = null;
        if (id != null) {
            list = list(new QueryWrapper<MediaPoint>().eq("code", code).eq("status", 1).ne("id", id).isNull("deleted_at"));
        } else {
            list = list(new QueryWrapper<MediaPoint>().eq("code", code).eq("status", 1).isNull("deleted_at"));
        }
        if (CollectionUtils.isNotEmpty(list)) {
            return false;
        }
        return true;
    }

    @Override
    public boolean checkABCode(String code, Long building_area_id, Long id) {
        if (code == null) {
            throw new CommonException("需要校验编码为空，请传入");
        }
        List<MediaPoint> list = null;
        List<MediaPoint> list2 = new ArrayList<>();
        List<MediaPoint> list3 = new ArrayList<>();
        if (id != null) {
            list = list(new QueryWrapper<MediaPoint>().eq("building_area_id", building_area_id).eq("status", 1).ne("id", id).isNull("deleted_at"));
            for (MediaPoint point : list) {
                String s = point.getCode().split("-")[0];
                if (s != null) {
                    if (code.length() > 2) {
                        if (s.substring(0, 2).equals(code.substring(0, 2))) {
                            list3.add(point);
                        }
                    }
                }
            }
            if (list3.size() > 0) {
                return false;
            }
        } else {
            list = list(new QueryWrapper<MediaPoint>().eq("status", 1).eq("building_area_id", building_area_id).isNull("deleted_at"));
            for (MediaPoint point : list) {
                String s = point.getCode().split("-")[0];
                if (s != null) {
                    if (s.substring(0, 1).equals(code.substring(0, 1))) {
                        list2.add(point);
                    }
                }
            }
            if (list2.size() > 0) {
                return false;
            }
        }

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean bindMarketPoint(MediaPoint dto) {
        MediaPoint mp = baseMapper.selectById(dto); // 修改前的数据mp
        if (mp == null) {
            return false;
        }
        // 如果编辑的当前点位code前面的字母加数字未修改 不修改ab绑定信息 直接修改media_point表信息
        String s = mp.getCode().split("-")[0];
        if (s != null) {
            if (s.substring(0, 2).equals(dto.getCode().substring(0, 2))) {
                updateById(dto);
                return true;
            }
        }
        // 否则先将原来的code的关联信息删除
        try {
            mediaPointABMapper.deleteBefore(dto.getId());
            // 查询如今的code是否存在对应关联数据 若存在 关联表插入数据 最后修改
            String ss = dto.getCode().substring(1, 2);
            String s1 = dto.getCode().substring(1, 2).equals("1") ? "2" : "1";
            String code = dto.getCode().substring(0, 1) + s1; // 编辑的code的对应面code
            List<MediaPoint> list = list(new QueryWrapper<MediaPoint>().eq("building_area_id", dto.getBuilding_area_id()).ne("id", dto.getId()).isNull("deleted_at"));
            MediaPoint mediaPoint = new MediaPoint(); // 是否存在对应面数据
            for (MediaPoint point : list) {
                if (point.getCode().substring(0, 2).equals(code)) {
                    mediaPoint = point;
                    break;
                }
            }

            if (mediaPoint.getId() != null) {  // 若存在对应面数据 插入关系表
                MediaPointAB mediaPointAB = new MediaPointAB();
                if (s1.equals("1")) {
                    mediaPointAB.setA_point_id(mediaPoint.getId());
                    mediaPointAB.setB_point_id(dto.getId());
                } else {
                    mediaPointAB.setA_point_id(dto.getId());
                    mediaPointAB.setB_point_id(mediaPoint.getId());
                }

                mediaPointABService.save(mediaPointAB);
            }

            if (s1.equals("1")) {
                dto.setAb_type_id(58L);
            } else {
                dto.setAb_type_id(57L);
            }
            updateById(dto);
        } catch (Exception e) {
            log.error("修改市场网点失败");
            return false;
        }
        return true;
    }

    @Override
    public SpecialPointListVO selectSpecialList(MediaPointDTO searchDTO) {
        List<MediaPointVO> list = baseMapper.listMediaPoint(searchDTO);
        List<MediaPointHouseVO> new_list = new ArrayList<>();
        List<MediaPointAbVO> mediaPointAbVO_list = new ArrayList<>();
        SpecialPointListVO specialPointListVO = new SpecialPointListVO();
        if (CollectionUtils.isNotEmpty(list)) {
            // 已锁定的点位
            List<Long> lockPointIds = mediaPointOccupySnapshotService.getLockPointIdsByIds(list.stream().map(MediaPointVO::getId).collect(Collectors.toList()));
            // 已上刊的点位
            List<Long> publishMediaPointIds = baseMapper.getPublishMediaPointIds(list.stream().map(MediaPointVO::getId).collect(Collectors.toList()));
            // 空闲 锁定 上刊点位
            specialPointListVO.setFreeCount(list.size() - lockPointIds.size());
            specialPointListVO.setLockCount(lockPointIds.size() - publishMediaPointIds.size());
            specialPointListVO.setOptionalCount(publishMediaPointIds.size());
            Map<String, MediaPointHouseVO> mapMediaPointHouse = new HashMap<>();
            for (MediaPointVO vo : list) {
                //设置预留锁定字段
                if (publishMediaPointIds.contains(vo.getId())) {
                    // 1 已上刊  2 锁定中 3 空闲中
                    vo.setLock_status(1);
                } else if (lockPointIds.contains(vo.getId())) {
                    vo.setLock_status(2);
                } else {
                    vo.setLock_status(3);
                }
                String building_number = vo.getBuilding_number();
                String unit_number = vo.getUnit_number();
                String floor_number = vo.getFloor();

                if (StringUtils.isNotBlank(building_number)) {
                    if (!mapMediaPointHouse.containsKey(building_number)) {
                        MediaPointHouseVO mediaPointHouseVO = new MediaPointHouseVO();
                        mediaPointHouseVO.setBuildingName(building_number + "号楼");
                        mediaPointHouseVO.setBuilding_number(building_number);
                        List<MediaPointUnitVO> listMediaPointUnitVO = new ArrayList<>();
                        mediaPointHouseVO.setUnitList(listMediaPointUnitVO);
                        Map<String, MediaPointUnitVO> unitMap = new HashMap<>();
                        mediaPointHouseVO.setUnitMap(unitMap);
                        mapMediaPointHouse.put(building_number, mediaPointHouseVO);
                        new_list.add(mediaPointHouseVO);
                        Collections.sort(new_list);
                    }
                }
                if (StringUtils.isNotBlank(unit_number)) {
                    MediaPointHouseVO mediaPointHouseVO = mapMediaPointHouse.get(building_number);
                    List<MediaPointUnitVO> listMediaPointUnitVO = mediaPointHouseVO.getUnitList();
                    Map<String, MediaPointUnitVO> unitMap = mediaPointHouseVO.getUnitMap();
                    if (!unitMap.containsKey(unit_number)) {
                        MediaPointUnitVO mediaPointUnitVO = new MediaPointUnitVO();
                        mediaPointUnitVO.setUnitName(unit_number + "单元");
                        mediaPointUnitVO.setUnit_number(unit_number);
                        List<MediaPointFloorVO> floorList = new ArrayList<>();
                        mediaPointUnitVO.setFloorList(floorList);
                        Map<String, MediaPointFloorVO> floorMap = new HashMap<>();
                        mediaPointUnitVO.setFloorMap(floorMap);

                        listMediaPointUnitVO.add(mediaPointUnitVO);
                        unitMap.put(unit_number, mediaPointUnitVO);
                        Collections.sort(listMediaPointUnitVO);
                        mediaPointHouseVO.setUnitList(listMediaPointUnitVO);
                        mediaPointHouseVO.setUnitMap(unitMap);

                    }
                }
                if (StringUtils.isNotBlank(floor_number)) {
                    MediaPointHouseVO mediaPointHouseVO = mapMediaPointHouse.get(building_number);
                    Map<String, MediaPointUnitVO> unitMap = mediaPointHouseVO.getUnitMap();
                    MediaPointUnitVO mediaPointUnitVO = unitMap.get(unit_number);
                    List<MediaPointFloorVO> floorList = mediaPointUnitVO.getFloorList();
                    Map<String, MediaPointFloorVO> floorMap = mediaPointUnitVO.getFloorMap();
                    if (!floorMap.containsKey(floor_number)) {
                        MediaPointFloorVO mediaPointFloorVO = new MediaPointFloorVO();
                        mediaPointFloorVO.setFloorName(floor_number);
                        mediaPointFloorVO.setFloor_number(Integer.parseInt(floor_number));
                        List<MediaPointVO> pointList = new ArrayList<>();
                        pointList.add(vo);
                        mediaPointFloorVO.setPointInformationList(pointList);
                        Collections.sort(floorList);
                        floorList.add(mediaPointFloorVO);
                        floorMap.put(floor_number, mediaPointFloorVO);
                    } else {
                        MediaPointFloorVO MediaPointFloorVO = floorMap.get(floor_number);
                        List<MediaPointVO> pointList = MediaPointFloorVO.getPointInformationList();
                        pointList.add(vo);
                        MediaPointFloorVO.setPointInformationList(pointList);
                    }
                }

                //构造ab面
                MediaPointAbVO mediaPointAbVO = null;
                Long ab_type_id = vo.getAb_type_id();
                Long seach_ab_type_id = searchDTO.getAb_type_id();
                if (ab_type_id != null && ab_type_id == 57L && seach_ab_type_id == null) {
                    List<MediaPointVO> pointList = new ArrayList<>();
                    Long a_point_id = vo.getId();
                    AbMediaPointDTO b_point = baseMapper.getBpointByAPointId(a_point_id);
                    MediaPointVO b_mediaPointVO = new MediaPointVO();
                    pointList.add(vo);
                    if (b_point != null) {
                        b_point.setLock_status(vo.getLock_status());
                        BeanUtils.copyProperties(b_point, b_mediaPointVO);
                        pointList.add(b_mediaPointVO);
                    }
                    mediaPointAbVO = new MediaPointAbVO();
                    mediaPointAbVO.setUnitList(pointList);
                } else if (ab_type_id != null && ab_type_id == 57L && seach_ab_type_id == 57L) {
                    List<MediaPointVO> pointList = new ArrayList<>();
                    pointList.add(vo);
                    mediaPointAbVO = new MediaPointAbVO();
                    mediaPointAbVO.setUnitList(pointList);
                }
                if (ab_type_id != null && ab_type_id == 58L && seach_ab_type_id == null) {
                    Long b_point_id = vo.getId();
                    AbMediaPointDTO a_point = baseMapper.getApointByBPointId(b_point_id);
                    if (a_point != null && a_point.getId() != null) {
                        continue;
                    } else {
                        List<MediaPointVO> pointList = new ArrayList<>();
                        pointList.add(vo);

                        mediaPointAbVO = new MediaPointAbVO();
                        mediaPointAbVO.setUnitList(pointList);
                    }
                } else if (ab_type_id != null && ab_type_id == 58L && seach_ab_type_id == 58L) {
                    List<MediaPointVO> pointList = new ArrayList<>();
                    pointList.add(vo);

                    mediaPointAbVO = new MediaPointAbVO();
                    mediaPointAbVO.setUnitList(pointList);
                }
                if (mediaPointAbVO != null) {
                    mediaPointAbVO_list.add(mediaPointAbVO);
                }

            }

            specialPointListVO.setMediaPointHouseList(new_list);
            specialPointListVO.setMediaPointAbVO(mediaPointAbVO_list);
        }
        return specialPointListVO;
    }

    @Override
    public boolean saveImportAbList(List<ImportAbPointDTO> list, Long building_area_id) {
        List<MediaPointDTO> new_list = new ArrayList<>();
        for (ImportAbPointDTO pointDTO : list) {
            pointDTO.setBuilding_area_id(building_area_id);
            if (pointDTO.getCode() == null && pointDTO.getB_code() != null) {
                throw new CommonException("存在没填a面信息的数据，请核验！");
            }
            MediaPointDTO a_point = new MediaPointDTO();
            BeanUtils.copyProperties(pointDTO, a_point);
            a_point.setAb_type_id(57L);
            //解析b面

            if (StringUtils.isNotBlank(pointDTO.getB_code())) {
                AbMediaPointDTO b_point = new AbMediaPointDTO();
                b_point.setBuilding_area_id(building_area_id);
                b_point.setCode(pointDTO.getB_code());
                b_point.setAb_type_id(58L);
                b_point.setMedia_type_id(pointDTO.getB_media_type_id());
                b_point.setPic_type_id(pointDTO.getB_pic_type_id());
                b_point.setLocation(pointDTO.getB_location());
                b_point.setSize_width(pointDTO.getB_size_width());
                b_point.setSize_height(pointDTO.getB_size_height());
                b_point.setSize_width_inside(pointDTO.getB_size_width_inside());
                b_point.setSize_height_inside(pointDTO.getB_size_height_inside());
                b_point.setIs_light(pointDTO.getB_is_light());
                a_point.setBpoint(b_point);
            }

            new_list.add(a_point);
        }
        return saveList(new_list);
    }

    /**
     * @param response
     * @param startDate
     * @param endDate
     * @param building_ids
     */
    @Override
    public void exportLeaveUnusedPointExcel(HttpServletResponse response, LocalDate startDate, LocalDate endDate, List<Long> building_ids, List<Long> media_type_ids, Boolean floor_group, Integer ABType) {
        //获取点位类型的map
        Map<Long, String> pointTypeMap = mediaTypeService.list().stream().collect(Collectors.toMap(MediaType::getId, MediaType::getName));
        // 根据id查询楼盘数据
        List<BuildingArea> list = buildingAreaService.list(Wrappers.<BuildingArea>lambdaQuery().in(BuildingArea::getId, building_ids));
        //按照buildingTypeId类型分类
        Map<Long, List<BuildingArea>> map = list.stream().collect(groupingBy(BuildingArea::getType_id));
        // 按照楼盘ID将list转为map
        Map<Long, Long> buildingTypeMap = list.stream().collect(Collectors.toMap(BuildingArea::getId, BuildingArea::getType_id));
        // 获取BuildingInfo集合
        List<BuildingInfo> collect = list.stream().map(item -> {
            BuildingInfo info = new BuildingInfo();
            info.setId(item.getId());
            return info;
        }).collect(Collectors.toList());
        // 获取点位类型id集合
        List<Long> pointTypeIds = new ArrayList<>();
//        for (Long typeId : map.keySet()) {
//            BuildingCorrespondingPointEnum buildingCorrespondingPointEnum = BuildingCorrespondingPointEnum.getByBuildingTypeId(typeId);
//            pointTypeIds.addAll(Arrays.asList(buildingCorrespondingPointEnum.getPoint_type_id()));
//        }
        // todo 修改为数据库的楼盘和媒体类型对应关系 若传入的搜索媒体类型是空的就使用楼盘和媒体类型对应关系进行搜索
        Map<Long, List<BuildingAreaTypeMediaTypeRelation>> buildingAreaTypeMediaTypeRelationMap = buildingAreaTypeMediaTypeRelationMapper.selectList(Wrappers.lambdaQuery()).stream().collect(groupingBy(BuildingAreaTypeMediaTypeRelation::getBuilding_area_type_id));
        if (media_type_ids == null || media_type_ids.size() == 0) {
            map.keySet().forEach(type_id -> {
                if (buildingAreaTypeMediaTypeRelationMap.containsKey(type_id)) {
                    List<BuildingAreaTypeMediaTypeRelation> buildingAreaTypeMediaTypeRelations = buildingAreaTypeMediaTypeRelationMap.get(type_id);
                    pointTypeIds.addAll(buildingAreaTypeMediaTypeRelations.stream().map(BuildingAreaTypeMediaTypeRelation::getMedia_type_id).collect(Collectors.toSet()));
                }
            });
        } else {
            pointTypeIds.addAll(media_type_ids);
        }
        PointProcessSearchDTO dto = new PointProcessSearchDTO();
        dto.setBeginDate(startDate);
        dto.setEndDate(endDate);
        dto.setBuildingList(collect);
        dto.setPointTypeIdList(pointTypeIds);
        dto.setBuildingRadiation(false);
//        if (ABType == 1) {
//            dto.setAbType(AbType.A);
//        } else if (ABType == 2) {
//            dto.setAbType(AbType.B);
//        } else if (ABType == 3) {
//            dto.setAbType(AbType.AB);
//        } else {
//            dto.setAbType(AbType.ALL);
//        }
        // 搜索数据
        List<BuildingPointVO> result = intentionSchemeService.search(dto);
        result.forEach(item -> {
            item.setType_id(buildingTypeMap.get(item.getId()));
        });
        String now = LocalDate.now().format(formatter);
        List<File> fileList = new ArrayList<>();
        // 获取每个类型的楼盘数据
        Map<Long, List<BuildingPointVO>> dataMap = result.stream().collect(groupingBy(BuildingPointVO::getType_id));
        for (Long typeId : dataMap.keySet()) {
            BuildingCorrespondingPointEnum pointEnum = BuildingCorrespondingPointEnum.getByBuildingTypeId(typeId);
            String fileName = tmpPath + File.separator + pointEnum.getName() + "类型" + now + System.currentTimeMillis() + ".xls";
            List<BuildingAreaTypeMediaTypeRelation> buildingAreaTypeMediaTypeRelations = buildingAreaTypeMediaTypeRelationMap.get(typeId);
            List<Long> point_type_list = buildingAreaTypeMediaTypeRelations.stream().map(BuildingAreaTypeMediaTypeRelation::getMedia_type_id).distinct().collect(Collectors.toList());
            List<Long> point_type_list_smart_box = point_type_list.stream().filter(i -> i == 1).collect(Collectors.toList()); // 是否包含智能框
            List<Long> point_type_list_other = point_type_list.stream().filter(i -> i != 1).collect(Collectors.toList());
            HSSFWorkbook excel = new HSSFWorkbook();
            // 智能框 + 住宅 导出excel需要重新处理
            if (CollectionUtils.isNotEmpty(point_type_list_smart_box) && BuildingCorrespondingPointEnum.RESIDENCE.getBuilding_type_id().equals(typeId)) {
                List<BuildingPointVO> voList = dataMap.get(typeId);
                List<Long> buildingIds = voList.stream().map(BuildingPointVO::getId).collect(Collectors.toList());
                List<JSONObject> jsonList = buildingAreaMapper.getBuildingAreaBySmartBox(buildingIds);
                excel = createExcelBySmartBox(voList, jsonList, point_type_list_smart_box, pointTypeMap, startDate, endDate, floor_group);
            } else {
                excel = createExcel(dataMap.get(typeId), typeId, point_type_list_other, pointTypeMap, startDate, endDate, floor_group, ABType);
            }
            File file = new File(fileName);
            fileList.add(file);
            FileOutputStream out = null;
            try {
                if (!file.exists()) {
                    file.createNewFile();
                }
                out = new FileOutputStream(file);
                excel.write(out);
                out.flush();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (out != null) {
                    try {
                        out.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        String zipFilePath = null;
        FileInputStream input = null;
        try {
            zipFilePath = FileUtil.zipFile(fileList, tmpPath + File.separator + "导出空位" + System.currentTimeMillis());
            File zip = new File(zipFilePath);
            input = new FileInputStream(zip);
            ServletOutputStream out = response.getOutputStream();
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("test.zip", "UTF-8"));
            byte[] bytes = new byte[1024];
            while (input.read(bytes) != -1) {
                out.write(bytes);
            }
            out.flush();
            input.close();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (zipFilePath != null) {
                FileUtil.delFile(zipFilePath);// 删除文件
                for (File file : fileList) {
                    file.delete();
                }
            }
        }

    }

    @Override
    public String exportLeaveUnusedPointExcelAndUploadOSS(LocalDate startDate, LocalDate endDate, List<Long> building_ids, List<Long> meda_type_ids, Boolean floor_group, Integer ABType) {
        //获取点位类型的map
        Map<Long, String> pointTypeMap = mediaTypeService.list().stream().collect(Collectors.toMap(MediaType::getId, MediaType::getName));
        // 根据id查询楼盘数据
        List<BuildingArea> list = buildingAreaService.list(Wrappers.<BuildingArea>lambdaQuery().in(BuildingArea::getId, building_ids));
        //按照buildingTypeId类型分类
        Map<Long, List<BuildingArea>> map = list.stream().collect(groupingBy(BuildingArea::getType_id));
        // 按照楼盘ID将list转为map
        Map<Long, Long> buildingTypeMap = list.stream().collect(Collectors.toMap(BuildingArea::getId, BuildingArea::getType_id));
        // 获取BuildingInfo集合
        List<BuildingInfo> collect = list.stream().map(item -> {
            BuildingInfo info = new BuildingInfo();
            info.setId(item.getId());
            return info;
        }).collect(Collectors.toList());
        // 获取点位类型id集合
        List<Long> pointTypeIds = new ArrayList<>();
        // todo 修改为数据库的楼盘和媒体类型对应关系 若传入的搜索媒体类型是空的就使用楼盘和媒体类型对应关系进行搜索
        Map<Long, List<BuildingAreaTypeMediaTypeRelation>> buildingAreaTypeMediaTypeRelationMap = buildingAreaTypeMediaTypeRelationMapper.selectList(Wrappers.lambdaQuery()).stream().collect(groupingBy(BuildingAreaTypeMediaTypeRelation::getBuilding_area_type_id));
        if (meda_type_ids == null || meda_type_ids.size() == 0) {
            map.keySet().forEach(type_id -> {
                if (buildingAreaTypeMediaTypeRelationMap.containsKey(type_id)) {
                    List<BuildingAreaTypeMediaTypeRelation> buildingAreaTypeMediaTypeRelations = buildingAreaTypeMediaTypeRelationMap.get(type_id);
                    pointTypeIds.addAll(buildingAreaTypeMediaTypeRelations.stream().map(BuildingAreaTypeMediaTypeRelation::getMedia_type_id).collect(Collectors.toSet()));
                }
            });
        } else {
            pointTypeIds.addAll(meda_type_ids);
        }
        PointProcessSearchDTO dto = new PointProcessSearchDTO();
        dto.setBeginDate(startDate);
        dto.setEndDate(endDate);
        dto.setBuildingList(collect);
        dto.setPointTypeIdList(pointTypeIds);
        dto.setBuildingRadiation(false);
        // 搜索数据
        List<BuildingPointVO> result = intentionSchemeService.search(dto);
        result.forEach(item -> {
            item.setType_id(buildingTypeMap.get(item.getId()));
        });
        // 获取每个类型的楼盘数据
        Map<Long, List<BuildingPointVO>> dataMap = result.stream().collect(groupingBy(BuildingPointVO::getType_id));
        HSSFWorkbook allExcel = new HSSFWorkbook();
        for (Long typeId : dataMap.keySet()) {
            BuildingCorrespondingPointEnum pointEnum = BuildingCorrespondingPointEnum.getByBuildingTypeId(typeId);
            String sheetName = pointEnum.getName() + "类型";
            List<BuildingAreaTypeMediaTypeRelation> buildingAreaTypeMediaTypeRelations = buildingAreaTypeMediaTypeRelationMap.get(typeId);
            List<Long> point_type_list = buildingAreaTypeMediaTypeRelations.stream().map(BuildingAreaTypeMediaTypeRelation::getMedia_type_id).distinct().collect(Collectors.toList());
            createSheet(allExcel, sheetName, dataMap.get(typeId), typeId, point_type_list, pointTypeMap, startDate, endDate, floor_group, ABType);
        }
        String workBookPath = "";
        FileInputStream input = null;
        FileOutputStream out = null;
        try {
            workBookPath = tmpPath + File.separator + "导出空位" + System.currentTimeMillis() + ".xls";
            File workBookFile = new File(workBookPath);
            out = new FileOutputStream(workBookFile);
            allExcel.write(out);
            out.close();
            input = new FileInputStream(workBookFile);
            MultipartFile multipartFile = new MockMultipartFile("file", workBookFile.getName(), "application/x-zip-compressed", IOUtils.toByteArray(input));
            return attachmentService.store2("", multipartFile.getInputStream(), multipartFile.getSize(), multipartFile.getContentType(), workBookFile.getName());
        } catch (Exception e) {
            e.printStackTrace();
            throw new CommonException("导出失败");
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (workBookPath != null) {
                FileUtil.delFile(workBookPath);// 删除文件
            }
        }
    }

    @Override
    public Page<MediaPointAreaVO> getUnlockedPoint(Integer current_page, Integer page_size, String adcode, Long building_id, String code, Long point_type_id, LocalDateTime start_time, LocalDateTime end_time) {
        Page<MediaPointAreaVO> page = new Page<>(current_page, page_size);
        List<Long> ids = baseMapper.getLockedPoint(start_time, end_time);
        List<MediaPointAreaVO> unlockedPoint = baseMapper.getUnlockedPoint(page, adcode, building_id, code, point_type_id, ids);
        page.setRecords(unlockedPoint);
        return page;
    }

    @Override
    public Page<MediaPointCountVO> page(Integer current_page, Integer page_size, String code, Long building_area_id, Long media_type_id, String adcode) {
        Page<MediaPointCountVO> page = new Page<>(current_page, page_size);
        List<MediaPointCountVO> list = baseMapper.page(page, code, building_area_id, media_type_id, adcode);
        List<Long> collect = list.stream().filter(item -> item.getLatest_audit_id() != null).map(MediaPoint::getLatest_audit_id).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(collect)) {
            Map<Long, List<WorkerSubmitPhoto>> map = workerSubmitPhotoService.list(Wrappers.<WorkerSubmitPhoto>lambdaQuery().in(WorkerSubmitPhoto::getWorker_submit_id, collect)).stream().collect(groupingBy(WorkerSubmitPhoto::getWorker_submit_id));
            for (MediaPointCountVO mediaPointCountVO : list) {
                List<WorkerSubmitPhoto> workerSubmitPhotos = map.get(mediaPointCountVO.getLatest_audit_id());
                if (workerSubmitPhotos != null) {
                    mediaPointCountVO.setImgList(workerSubmitPhotos.stream().map(WorkerSubmitPhoto::getUrl).collect(Collectors.toList()));
                }
            }
        }
        page.setRecords(list);
        return page;
    }
}
